home *** CD-ROM | disk | FTP | other *** search
Text File | 1985-02-05 | 15.6 KB | 361 lines | [TEXT/ttxt] |
- /* ----------------------------------------------------------------------------------
- NAME
- Scroll
-
- DESCRIPTION
- This code demonstrates how to use scroll bars.
- You can scroll text or graphics or both.
- You can scroll horizontally or vertically.
-
- AUTHOR
- Cary Clark, Macintosh Technical Support
- Copyright 1984 Apple Computer Inc.
-
- ---------------------------------------------------------------------------------- */
-
- #include "mac/c/include/interface.h" /* Macintosh definitions and functions */
-
- #define Horizontal 1 /* These are the choices in the menu "Scroll Bar". */
- #define Vertical 2
- #define TextItem 4
- #define Graphics 5
-
- #define FileMenu 1 /* resource numbers and position in the Menu bar */
- #define ScrollMenu 2
-
- #define NumOfRects 30 /* quantity of rectangles and strings to scroll around */
- #define NumOfStrings 55
-
- /* The graphics scrolled in this example are an array of rectangles. */
- typedef Rect MyRectData[NumOfRects], (**MyRectHdl)[NumOfRects]; /* */
-
-
- TEHandle hTE; /* TextEdit handle */
- ControlHandle hScroll, /* horizontal scroll bar */
- vScroll; /* vertical scroll bar */
- WindowPtr myWindow; /* document window */
- MenuHandle hdlScrollMenu; /* handle to the menu items */
- MyRectHdl myRect; /* handle to array of rectangles */
- short originalPart; /* 1st part of the scroll bar hit */
- Point pageCorner, /* location of the upper left hand page corner */
- eventPoint; /* where an event took place */
- Rect growBoxRect, /* area of the window reserved for the grow box */
- myViewRect; /* display rectangle containing scrollable data */
- Boolean doneFlag = false, /* set true when the user selects 'Quit' */
- showText = true, /* set true when text can be scrolled */
- showGraphics = false; /* set true when graphics can be scrolled */
-
- SetUpData() /* ------------------------------------------------------------------- */
-
- /* This procedure initializes two data structures; a TextEdit record and an array of
- rectangles. Initially, only text and the vertical scrollbar will be displayed. */
- {
- StringHandle myString; /* temporary container for a string in the resource fork */
- short counter; /* counters must be local to the procedure */
- Rect destRect; /* rectangle containing the larger-than-the-screen page */
-
-
- /* The TextEdit record is initialized by reading in a string from the application's
- resource fork and then inserting it a number of times into the TextEdit record. */
-
- myString = GetString(256); /* Get some text to play around with. */
-
- /* Set the view as the portrect less the vertical scrollbar area. The TextEdit
- destRect will be set to the current window width plus an arbitrary value. */
-
- myViewRect = myWindow->portRect;
- destRect = myViewRect;
- destRect.right += 300;
- pageCorner.h = -destRect.left;
- pageCorner.v = -destRect.top;
- myViewRect.right -= 15; /* subtract width of scrollbar */
- hTE = TENew(&destRect, &myViewRect);
-
- HLock(myString); /* can't move if we are going to point to the text */
- /* Create a TextEdit record full of the string. */
- for (counter = 1; counter <= NumOfStrings; ++counter)
- TEInsert(&(**myString).text[0], (**myString).length, hTE);
- HUnLock(myString); /* free to move again */
-
- /* Now, create a structure of rectangles. */
- myRect = (MyRectHdl) NewHandle(sizeof(MyRectData)); /* 240 bytes */
- for (counter = 1; counter <= NumOfRects; ++counter)
- SetRect(&(**myRect)[counter - 1], counter * 23, counter * 20, counter * 23 + 50,
- counter * 20 + 50);
-
- ShowWindow(myWindow); /* Display the window and the text it contains */
-
- vScroll = GetNewControl(256, myWindow); /* vertical scrollbar */
- hScroll = GetNewControl(257, myWindow); /* horizontal scrollbar, not shown */
- SetRect(&growBoxRect, (**vScroll).contrlRect.left+1,
- (**vScroll).contrlRect.bottom+1, myWindow->portRect.right,
- myWindow->portRect.bottom); /* This area is set up for ValidRect, below. */
-
- CheckItem(hdlScrollMenu, Vertical, true);
- CheckItem(hdlScrollMenu, TextItem, true);
- } /* end of SetUpData */
-
-
- GrafUpdate(whatpart) /* ---------------------------------------------------------- */
- Rect whatpart;
- /* This is roughly the equivalent of what TEUpdate does with text. The upper left
- hand corner of the page is moved up and to the left to simulate a view further down
- and to the right. To more accurately resemble a Toolbox routine like TEUpdate, this
- procedure should also preserve the current clip region and origin. */
- {
- short count;
- Rect dummyRect;
-
- SetOrigin(pageCorner.h, pageCorner.v); /* negative moves the origin left, up */
- OffsetRect(&whatpart, pageCorner.h, pageCorner.v); /* also move update rect */
- ClipRect(&whatpart); /* only redraw the portion that the user requests */
- for (count = 0; count < NumOfRects; ++count)
- /* Redraw the object if it intersects the update rectangle */
- if (SectRect(&(**myRect)[count], &whatpart, &dummyRect))
- FrameRect(&(**myRect)[count]);
- SetOrigin(0,0); /* reset the origin back to the upper left hand corner */
- ClipRect(&myWindow->portRect); /* reset the clip region to the entire window */
- } /* end of GrafUpdate */
-
-
- ScrollBits() /* ------------------------------------------------------------------ */
- /* This routine scrolls horizontally and vertically both graphics and text. If you
- are only scrolling text, only the TEScroll is required. If you are only scrolling
- graphics, then only the ScrollRect and GrafUpDate is needed. */
-
- {
- short vChange,
- hChange,
- vScrollValue,
- hScrollValue;
- RgnHandle anUpdateRgn;
-
- vScrollValue = GetCtlValue(vScroll); /* These values will be used a lot so they */
- hScrollValue = GetCtlValue(hScroll); /* are read into temporary variables. */
-
- /* Find the vertical and horizontal change. */
- vChange = pageCorner.v - vScrollValue; /* the vertical difference */
- hChange = pageCorner.h - hScrollValue; /* the horizontal difference */
-
- /* Record the values for next time */
- pageCorner.v = vScrollValue;
- pageCorner.h = hScrollValue;
-
- /* For pure text, only a TEScroll is required. */
- if (!showGraphics && showText) TEScroll(hChange, vChange, hTE);
-
- /* For graphics, a ScrollRect will move the visible bits on the screen. The
- region returned by ScrollRect indicates what part of the window needs to
- be updated. */
- if (showGraphics) {
- anUpdateRgn = NewRgn();
- ScrollRect(&myViewRect, hChange, vChange, anUpdateRgn);
-
- /* This draws the new text. The clipping is necessary because normally
- TextEdit redraws the entire character height and perhaps only a partial
- character scroll was done. Since TextEdit erases before it draws, the text,
- if any, is drawn before the graphics. */
- if (showText) {
- (**hTE).destRect.left = -hScrollValue;
- (**hTE).destRect.top = -vScrollValue;
- ClipRect(&(**anUpdateRgn).rgnBBox);
- TEUpdate(&(**anUpdateRgn).rgnBBox, hTE);
- ClipRect(&(myWindow->portRect));
- } /* end of showText */
-
- GrafUpdate((**anUpdateRgn).rgnBBox); /* Fill in the newly exposed region */
- DisposeRgn(anUpdateRgn);
- } /* end of showGraphics */
- } /* end of ScrollBits */
-
- pascal void TrackScroll(theControl, partCode) /*---------------------------------- */
- ControlHandle theControl;
- short partCode;
- /*This routine adjusts the value of the scrollbar. A reasonable change would
- be to adjust the minimum scroll amount to equal the text's lineheight. */
- {
- short amount,
- startValue;
- Boolean up;
-
- up = (partCode == inUpButton) || (partCode == inPageUp); /*true if scrolling up */
- startValue = GetCtlValue(theControl); /*the initial control value */
-
- if /*the scrollbar value is decreased, and it is not already at the minimum */
- ( ((up && (startValue > GetCtlMin(theControl)))
- || /*the scrollbar value is increased, and it is not already at the maximum */
- ((! up) && (startValue < GetCtlMax(theControl))))
- && /* to prevent tracking if the page up or down area disappears */
- (originalPart == partCode) ) {
- if (up)
- amount = -1;
- else
- amount = 1; /* Set the direction. */
- if ((partCode == inPageUp) || (partCode == inPageDown)) {
- /* Change the movement to a full page. */
- if (theControl == vScroll)
- amount *= myViewRect.bottom - myViewRect.top;
- else
- amount *= myViewRect.right - myViewRect.left;
- } /* end of partCode */
- SetCtlValue(theControl, startValue + amount);
- ScrollBits();
- }
- } /* end of TrackScroll */
-
- MyControls() /* ------------------------------------------------------------------ */
- /* respond to a mouse down event in one of the controls */
- {
- short dummy;
- ControlHandle theControl;
-
- /* return control and part */
- originalPart = FindControl(&eventPoint, myWindow, &theControl);
- if (originalPart == inThumb) {
- /* The thumb is tracked until it is released; then the bits are scrolled. */
- dummy = TrackControl(theControl, &eventPoint, nil);
- ScrollBits();
- } /* end of whichpart */
- /* For the arrows and the page changes, scroll while the mouse is held down. */
- else dummy = TrackControl(theControl, &eventPoint, TrackScroll);
- } /* end of MyControls */
-
- MainEventLoop() /*---------------------------------------------------------------- */
- /* respond to menu selections, the scrollbars, and update events */
- {
- EventRecord myEvent; /* all of the information about the event */
- int menuResult; /* information returned by MenuSelect */
- short theMenu, /* which menu was selected */
- theItem; /* which item within the menu */
- Boolean checked; /* Is the menu item checked? */
- short markChar; /* the checkmark character */
- WindowPtr tempWindow;
- Rect tempRect;
-
- do {
- checked = GetNextEvent(everyEvent,&myEvent); /*checked here is ignored */
- switch(myEvent.what) {
- case mouseDown: /* The user pressed or is holding the mouse button down. */
- switch(FindWindow(&myEvent.where,&tempWindow)) {
- case inMenuBar: /*the mouseDown was in the menu bar */
- menuResult = MenuSelect(&myEvent.where);
- theMenu = HiWord(menuResult);
- theItem = LoWord(menuResult);
- switch(theMenu) {
- case FileMenu:
- doneFlag = true; /* Quit */
- break;
- case ScrollMenu:
- /* The items in the menu are used to keep track of the user has chosen thus far.
- These lines toggle the checkmark in the menu and leave the result in the variable
- 'checked'. */
- GetItemMark(hdlScrollMenu, theItem, &markChar);
- checked = (markChar != checkMark);
- CheckItem(hdlScrollMenu, theItem, checked);
-
- /* Any selection will cause some part of the screen to be redrawn. The selection
- that the user makes causes some part of the screen to become invalid. */
- if ((theItem == TextItem) || (theItem == Graphics)) {
- InvalRect(&myViewRect);
- /* The small area between the scrollbars reserved for the grow box should never be
- redrawn. */
- ValidRect(&growBoxRect);
- }
- switch(theItem) {
- case Horizontal:
- InvalRect(&(**hScroll).contrlRect);
- if (checked) {
- ShowControl(hScroll);
- myViewRect.bottom = (**hScroll).contrlRect.top;
- } /* end of checked */
- else { /* not checked */
- HideControl(hScroll);
- myViewRect.bottom = (**hScroll).contrlRect.bottom;
- } /* end of not checked */
- break; /* end of horizontal */
-
- case Vertical:
- InvalRect(&(**vScroll).contrlRect);
- if (checked) {
- ShowControl(vScroll);
- myViewRect.right = (**vScroll).contrlRect.left;
- } /* end of checked */
- else { /*not checked */
- HideControl(vScroll);
- myViewRect.right = (**vScroll).contrlRect.right;
- } /* end of not checked */
- break; /* end of vertical */
-
- case TextItem:
- /* Since we dereference the destRect into tempRect, no calls in the scope of this
- statement should cause a memory compaction. */
- showText = checked;
- if (checked) {
- (**hTE).destRect.top = -GetCtlValue(vScroll);
- (**hTE).destRect.left = -GetCtlValue(hScroll);
- } /* end of checked */
- break; /* end of textItem */
-
- case Graphics:
- showGraphics = checked;
- break;
- } /* end of theItem switch */
- if (showText)
- (**hTE).viewRect = myViewRect;
- break; /* end of case ScrollMenu */
- } /* end of theMenu switch */
- HiliteMenu(0);
- break; /* end of case inMenuBar: */
-
- case inContent:
- /* Rectangles making up controls are the part of the window outside the 'view'. */
- eventPoint = myEvent.where;
- GlobalToLocal(&eventPoint);
- if (!PtInRect(&eventPoint, &myViewRect))
- MyControls();
- break; /* end of case inContent: */
- } /* end of FindWindow switch */
- break; /* end of case mouseDown: */
-
- case updateEvt:
- /* In response to InvalRects, the appropriate text or graphics is erased and redrawn.
- The BeginUpdate causes the VisRgn to be replaced by the intersection of the VisRgn
- and the UpdateRgn. */
- BeginUpdate(myWindow);
- EraseRect(&myViewRect); /*start with a clean slate */
- if (showText)
- TEUpdate(&(**(myWindow->visRgn)).rgnBBox, hTE);
- /* Call GrafUpdate with the intersection, if any, of the VisRgn and the view */
- if (showGraphics && SectRect(&(**myWindow->visRgn).rgnBBox, &myViewRect,
- &tempRect))
- GrafUpdate(tempRect);
- EndUpdate(myWindow);
- break; /* end of case updateEvent: */
- } /* end of myEvent.what switch */
- } /* end of do */
- while(!doneFlag);
- } /* end of event loop */
-
-
- main() /* ------------------------------------------------------------------------ */
- /* main program */
- {
- InitGraf(&qd.thePort); /* Initialize QuickDraw. */
- InitWindows(); /* Initialize Window Manager; clear desktop and menubar. */
- InitFonts(); /* Initialize Font Manager. */
- FlushEvents(everyEvent,0); /* Throw away any stray events. */
- TEInit(); /* Initialize TextEdit. */
- InitMenus(); /* Initialize Menu Manager. */
- hdlScrollMenu = GetMenu(FileMenu); /* (hdlScrollMenu is ignored.) */
- InsertMenu(hdlScrollMenu,0);
- hdlScrollMenu = GetMenu(ScrollMenu);
- InsertMenu(hdlScrollMenu,0);
- DrawMenuBar();
- myWindow = GetNewWindow(256, nil, (WindowPtr) -1); /* get window to work within */
- SetPort(myWindow); /* Point to a window. */
- TextFont(applFont); /* Select default application font. */
- SetUpData(); /* Initialize user data and controls. */
- InitCursor(); /* Change the watch into an arrow. */
- MainEventLoop(); /* Handle events until we are through. */
- }
-